﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
using System.Text.RegularExpressions;

namespace SerialPortAssistant
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void comboBox1_Click(object sender, EventArgs e)
        {
            comboBox1.Items.AddRange(SerialPort.GetPortNames());
        }
        private void btn_OpenSerial_Click(object sender, EventArgs e)
        {
            try
            {
                if (serialPort1.IsOpen == false)
                {
                    comboBox1.Enabled = false;
                    comboBox2.Enabled = false;
                    comboBox3.Enabled = false;
                    comboBox4.Enabled = false;
                    comboBox5.Enabled = false;
                    serialPort1.PortName = comboBox1.Text;
                    serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text);
                    serialPort1.DataBits = Convert.ToInt16(comboBox3.Text);

                    if (comboBox4.Text.Equals("None"))
                        serialPort1.Parity = Parity.None;
                    else if (comboBox4.Text.Equals("Odd"))
                        serialPort1.Parity = Parity.Odd;
                    else if (comboBox4.Text.Equals("Even"))
                        serialPort1.Parity = Parity.Even;
                    else if (comboBox4.Text.Equals("Mark"))
                        serialPort1.Parity = Parity.Mark;
                    else if (comboBox4.Text.Equals("Space"))
                        serialPort1.Parity = Parity.Space;

                    if (comboBox5.Text.Equals("1"))
                        serialPort1.StopBits = StopBits.One;
                    else if (comboBox5.Text.Equals("1.5"))
                        serialPort1.StopBits = StopBits.OnePointFive;
                    else if (comboBox5.Text.Equals("2"))
                        serialPort1.StopBits = StopBits.Two;

                    serialPort1.Open();
                    btn_OpenSerial.Text = "关闭串口";
                    btn_OpenSerial.BackColor = Color.Firebrick;

                    Tips.Text = "串口已打开！";
                    Tips.ForeColor = Color.Green;
                }
                else
                {
                    serialPort1.Close();
                    btn_OpenSerial.Text = "打开串口";
                    btn_OpenSerial.BackColor = Color.ForestGreen;
                    comboBox1.Enabled = true;
                    comboBox2.Enabled = true;
                    comboBox3.Enabled = true;
                    comboBox4.Enabled = true;
                    comboBox5.Enabled = true;
                    textBox_Receive.Text = "";
                    textBox_Send.Text = "";

                    Tips.Text = "串口已关闭！";
                    Tips.ForeColor = Color.Red;
                }
            }
            catch (Exception ex)
            {
                serialPort1 = new SerialPort();
                comboBox1.Items.Clear();
                comboBox1.Items.AddRange(SerialPort.GetPortNames());
                System.Media.SystemSounds.Beep.Play();
                btn_OpenSerial.Text = "打开串口";
                btn_OpenSerial.BackColor = Color.ForestGreen;
                MessageBox.Show(ex.Message);
                comboBox1.Enabled = true;
                comboBox2.Enabled = true;
                comboBox3.Enabled = true;
                comboBox4.Enabled = true;
                comboBox5.Enabled = true;
            }
        }

        private long receive_count = 0;
        private StringBuilder sb = new StringBuilder();
        private DateTime current_time = new DateTime();
        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int num = serialPort1.BytesToRead;      //获取接收缓冲区中的字节数
            byte[] received_buf = new byte[num];    //声明一个大小为num的字节数据用于存放读出的byte型数据

            receive_count += num;                   //接收字节计数变量增加nun
            serialPort1.Read(received_buf, 0, num);
            sb.Clear();     //防止出错,首先清空字符串构造器
                            //遍历数组进行字符串转化及拼接
            if (rb_HexRx.Checked)
            {
                //选中HEX模式显示
                foreach (byte b in received_buf)
                {
                    sb.Append(b.ToString("X2") + ' ');    //将byte型数据转化为2位16进制文本显示,用空格隔开
                }
            }
            else
            {
                //选中ASCII模式显示
                sb.Append(Encoding.ASCII.GetString(received_buf));  //将整个数组解码为ASCII数组
            }

            foreach (byte b in received_buf)
            {
                sb.Append(b.ToString());
            }
            Invoke((EventHandler)(delegate                          //委托
            {
                if (cb_ShowTime.Checked)
                {
                    //显示时间
                    current_time = System.DateTime.Now;     //获取当前时间
                    textBox_Receive.AppendText(current_time.ToString("HH:mm:ss") + "  " + sb.ToString());
                }
                else
                {
                    //不显示时间 
                    textBox_Receive.AppendText(sb.ToString());
                }
                Rx_Num.Text = "Rx:" + receive_count.ToString() + "Bytes";
            }
            )
            );

            try
            {
                this.Invoke((EventHandler)(delegate
                {
                    textBox_Receive.AppendText(serialPort1.ReadExisting());
                }
                   )
                );
            }
            catch (Exception ex)
            {
                System.Media.SystemSounds.Beep.Play();
                MessageBox.Show(ex.Message);
            }
        }

        private void btn_Clear_Click(object sender, EventArgs e)
        {
            textBox_Receive.Text = "";  //清空接收文本框
            textBox_Send.Text = "";     //清空发送文本框
            receive_count = 0;          //计数清零
            Rx_Num.Text = "Rx:" + receive_count.ToString() + "Bytes";   //刷新界面
        }

        int send_count = 0;
        private void btn_Send_Click(object sender, EventArgs e)
        {
            byte[] temp = new byte[1];
            try
            {
                if (serialPort1.IsOpen)
                {
                    int num = 0;

                    if (rb_HexTx.Checked)
                    {
                        string buf = textBox_Send.Text;
                        string pattern = @"\s";
                        string replacement = "";
                        Regex rgx = new Regex(pattern);
                        string send_data = rgx.Replace(buf, replacement);

                        num = (send_data.Length - send_data.Length % 2) / 2;
                        for (int i = 0; i < num; i++)
                        {
                            temp[0] = Convert.ToByte(send_data.Substring(i * 2, 2), 16);
                            serialPort1.Write(temp, 0, 1);
                        }
                        if (send_data.Length % 2 != 0)
                        {
                            temp[0] = Convert.ToByte(send_data.Substring(textBox_Send.Text.Length - 1, 1), 16);
                            serialPort1.Write(temp, 0, 1);
                            num++;
                        }
                        if (cb_SendNewline.Checked)
                        {
                            serialPort1.WriteLine("");
                        }
                    }
                    else
                    {
                        if (rb_AscllTx.Checked)
                        {
                            serialPort1.WriteLine(textBox_Send.Text);
                            num = textBox_Send.Text.Length + 2; //回车占两个字节
                        }
                        else
                        {
                            serialPort1.Write(textBox_Send.Text);
                            num = textBox_Send.Text.Length;
                        }
                    }

                    send_count += num;      //计数变量累加
                    Tx_Num.Text = "Tx:" + send_count.ToString() + "Bytes";   //刷新界面
                }
            }
            catch (Exception ex)
            {
                serialPort1.Close();
                serialPort1 = new System.IO.Ports.SerialPort();
                comboBox1.Items.Clear();
                comboBox1.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames());
                System.Media.SystemSounds.Beep.Play();
                btn_OpenSerial.Text = "打开串口";
                btn_OpenSerial.BackColor = Color.ForestGreen;
                MessageBox.Show(ex.Message);
                comboBox1.Enabled = true;
                comboBox2.Enabled = true;
                comboBox3.Enabled = true;
                comboBox4.Enabled = true;
                comboBox5.Enabled = true;
            }
        }

        private void cb_AutoSend_CheckedChanged(object sender, EventArgs e)
        {
            if (cb_AutoSend.Checked)
            {
                //自动发送功能选中,开始自动发送
                numericUpDown1.Enabled = false;     //失能时间选择
                timer1.Interval = (int)numericUpDown1.Value;     //定时器赋初值
                timer1.Start();     //启动定时器
                Tips.Text = "串口已打开!" + " 自动发送中...";
            }
            else
            {
                //自动发送功能未选中,停止自动发送
                numericUpDown1.Enabled = true;     //使能时间选择
                timer1.Stop();     //停止定时器
                Tips.Text = "串口已打开!";
            }
        }
    }
}
